package adminservices

import (
	"errors"
	"game-server/app/common/enum"
	"game-server/app/common/request"
	"game-server/app/models"
	"game-server/global"

	"gorm.io/gorm"
)

type sysRoleService struct{}

var SysRoleService = new(sysRoleService)

// GetAllRoles 获取所有角色
func (s *sysRoleService) GetAllRoles() ([]models.SysRole, error) {
	var roles []models.SysRole

	err := global.App.DB.Where("status = ?", enum.Enabled).
		Order("sort desc").
		Find(&roles).Error

	if err != nil {
		return nil, err
	}

	return roles, nil
}

// CreateRole 创建角色
func (s *sysRoleService) CreateRole(req request.SysRoleCreateRequest) (*models.SysRole, error) {
	// 检查角色编码是否已存在
	var count int64
	if err := global.App.DB.Model(&models.SysRole{}).Where("code = ?", req.Code).Count(&count).Error; err != nil {
		return nil, err
	}
	if count > 0 {
		return nil, errors.New("角色编码已存在")
	}

	// 创建角色
	role := &models.SysRole{
		Name: req.Name,
		Code: req.Code,
		Sort: req.Sort,

		Status: enum.Enabled,
		Remark: req.Remark,
	}
	// 开启事务
	// 开启事务
	err := global.App.DB.Transaction(func(tx *gorm.DB) error {
		// 创建用户
		if err := tx.Create(role).Error; err != nil {
			return err
		}

		// 如果有角色ID，则创建用户角色关联
		if len(req.MenuIds) > 0 {
			var menus []models.SysMenu
			if err := tx.Where("id IN ?", req.MenuIds).Find(&menus).Error; err != nil {
				return err
			}
			if err := tx.Model(role).Association("Menus").Replace(menus); err != nil {
				return err
			}
		}

		return nil
	})
	if err != nil {
		return nil, err
	}
	return role, nil
}

// 获取角色详情
func (s *sysRoleService) GetRoleDetail(id string) (*models.SysRole, error) {
	var role models.SysRole

	err := global.App.DB.Preload("Menus").First(&role, id).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New("角色不存在")
		}
		return nil, err
	}

	return &role, nil
}

// 删除角色
func (s *sysRoleService) DeleteRole(id string) error {
	var role models.SysRole

	// 查询角色是否存在
	if err := global.App.DB.First(&role, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New("角色不存在")
		}
		return err
	}

	// 检查是否为超级管理员角色
	if role.Code == "super_admin" {
		return errors.New("不能删除超级管理员角色")
	}

	// 检查角色是否已被用户使用
	var count int64
	if err := global.App.DB.Model(&models.SysUserRole{}).Where("role_id = ?", id).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("角色已被用户使用，不能删除")
	}

	return global.App.DB.Transaction(func(tx *gorm.DB) error {
		// 删除角色菜单关联
		if err := tx.Model(&role).Association("Menus").Clear(); err != nil {
			return err
		}

		// 软删除角色
		if err := tx.Delete(&role).Error; err != nil {
			return err
		}

		return nil
	})
}

// 批量删除角色
func (s *sysRoleService) BatchDeleteRoles(ids []uint) error {
	var roles []models.SysRole

	// 查询所有要删除的角色
	if err := global.App.DB.Where("id IN ?", ids).Find(&roles).Error; err != nil {
		return err
	}

	// 检查是否包含超级管理员角色
	for _, role := range roles {
		if role.Code == "super_admin" {
			return errors.New("不能删除超级管理员角色")
		}
	}

	// 检查角色是否已被用户使用
	var count int64
	if err := global.App.DB.Model(&models.SysUserRole{}).Where("role_id IN ?", ids).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("选中的角色中有已被用户使用的角色，不能删除")
	}

	return global.App.DB.Transaction(func(tx *gorm.DB) error {
		// 删除角色菜单关联
		for _, role := range roles {
			if err := tx.Model(&role).Association("Menus").Clear(); err != nil {
				return err
			}
		}

		// 批量软删除角色
		if err := tx.Delete(&models.SysRole{}, ids).Error; err != nil {
			return err
		}

		return nil
	})
}

// 分页条件查询角色
func (s *sysRoleService) GetRolePage(req request.SysRolePageRequest) (list []models.SysRole, total int64, err error) {
	limit := req.PageSize
	offset := req.PageSize * (req.Page - 1)

	// 构建查询
	db := global.App.DB.Model(&models.SysRole{})

	// 条件查询
	if req.Name != "" {
		db = db.Where("name LIKE ?", "%"+req.Name+"%")
	}
	if req.Code != "" {
		db = db.Where("code LIKE ?", "%"+req.Code+"%")
	}
	if req.Status != nil {
		db = db.Where("status = ?", *req.Status)
	}

	// 查询总数
	err = db.Count(&total).Error
	if err != nil {
		return nil, 0, err
	}

	// 查询数据
	err = db.Limit(limit).Offset(offset).
		Preload("Menus").
		Order("sort desc, id desc").
		Find(&list).Error
	if err != nil {
		return nil, 0, err
	}

	return list, total, nil
}

// 更新角色
func (s *sysRoleService) UpdateRole(req request.SysRoleUpdateRequest) error {
	var role models.SysRole
	if err := global.App.DB.First(&role, req.ID).Error; err != nil {
		return errors.New("角色不存在")
	}

	// 如果修改了角色编码，需要检查是否已存在
	if req.Code != role.Code {
		var count int64
		if err := global.App.DB.Model(&models.SysRole{}).Where("code = ? AND id != ?", req.Code, req.ID).Count(&count).Error; err != nil {
			return err
		}
		if count > 0 {
			return errors.New("角色编码已存在")
		}
	}

	// 不允许修改超级管理员角色的状态
	if role.Code == "super_admin" && req.Status != role.Status {
		return errors.New("不能修改超级管理员角色的状态")
	}

	// 更新角色信息
	role.Name = req.Name
	role.Code = req.Code
	role.Sort = req.Sort
	role.Status = req.Status
	role.Remark = req.Remark

	return global.App.DB.Transaction(func(tx *gorm.DB) error {
		// 更新角色基本信息
		if err := tx.Save(&role).Error; err != nil {
			return err
		}

		// 更新角色菜单关联
		if len(req.MenuIds) > 0 {

			// 先清除原有的角色菜单关联
			if err := tx.Model(&role).Association("Menus").Clear(); err != nil {
				return err
			}

			var menus []models.SysMenu
			if err := tx.Where("id IN ?", req.MenuIds).Find(&menus).Error; err != nil {
				return err
			}
			if err := tx.Model(&role).Association("Menus").Replace(menus); err != nil {
				return err
			}
		}

		return nil
	})
}

// 获取用户已分配的角色
func (s *sysRoleService) GetUserAssignedRoles(userId string) ([]models.SysRole, error) {
	var user models.SysUser

	// 查询用户是否存在
	if err := global.App.DB.First(&user, userId).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New("用户不存在")
		}
		return nil, err
	}

	// 获取用户的角色
	var roles []models.SysRole
	if err := global.App.DB.Model(&user).Association("Roles").Find(&roles); err != nil {
		return nil, err
	}

	return roles, nil
}

func (s *sysRoleService) AssignUserRoles(req request.SysRoleAssignRequest) error {
	var user models.SysUser

	// 查询用户是否存在
	if err := global.App.DB.First(&user, req.UserId).Error; err != nil {
		return errors.New("用户不存在")
	}

	// 查询要分配的角色是否都存在
	var roles []models.SysRole
	if err := global.App.DB.Where("id IN ?", req.RoleIds).Find(&roles).Error; err != nil {
		return err
	}
	if len(roles) != len(req.RoleIds) {
		return errors.New("部分角色不存在, 请重新选择")
	}

	// 检查角色状态
	for _, role := range roles {
		if role.Status != enum.Enabled {
			return errors.New("角色 " + role.Name + " 已被禁用")
		}
	}

	// 使用事务更新用户角色关联
	return global.App.DB.Transaction(func(tx *gorm.DB) error {
		// 清除原有角色关联
		if err := tx.Model(&user).Association("Roles").Clear(); err != nil {
			return err
		}

		// 建立新的角色关联
		if err := tx.Model(&user).Association("Roles").Replace(roles); err != nil {
			return err
		}

		return nil
	})
}
